package cn.com.hhrcw.utils.huawei;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @program: recruit-boot-parent
 * @author: JD
 * @create: 2020-12-25 13:25
 **/
@SuppressWarnings("AlibabaClassNamingShouldBeCamel")
@Slf4j
public class HmacSHA256 {

    private HmacSHA256() {}

    /**
     * 十六进制字符集
     */
    private static final char[] DIGEST_ARRAYS = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };

    /**
     * ExpireTime：鉴权签名材料Signature的过期时间戳。单位是秒。比如当前的系统的时间戳是1604020000，Signature有效期设置成10分钟，则ExpireTime = 1604020000+10*60 = 1604020600
     * Nonce：随机字符串，每次计算鉴权签名材料Signature时都必须不同。字符串长度为32~64字节
     * 功能：Signature生成算法
     * 输入参数：
     * 1.data: HMAC-SHA256的输入数据 = App ID + ":" + User ID + ":" + ExpireTime + ":" + Nonce
     * 2.key: App Key
     * 输出参数：十六进制字符串编码的HMAC-SHA256值
     */
    public static String encode(String data, String key) {
        byte[] hashByte;
        try {
            Mac sha256HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            sha256HMAC.init(secretKey);

            hashByte = sha256HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            return null;
        }

        return bytesToHex(hashByte);
    }

    /**
     * 功能：byte类型数组转换成十六进制字符串
     * 输入参数：
     * 1.bytes:被转换的字节数组
     * 输出参数：十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexStr = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            hexStr.append(DIGEST_ARRAYS[bytes[i] >>> 4 & 0X0F]);
            hexStr.append(DIGEST_ARRAYS[bytes[i] & 0X0F]);
        }
        return hexStr.toString();
    }

    /**
     * 获取精确到秒的时间戳
     *
     * @return
     */
    public static int getSecondTimestampTwo() {
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        return Integer.valueOf(timestamp);
    }

}
